<?php

namespace App\Service\Cruise\Check;

use App\Enums\Common\CommonEnum;
use App\Http\Middleware\OpenShop\MerchantAppAuth;
use App\Library\Rms\RmsShopApi;
use App\Models\Common\OperateLogModel;
use App\Models\Common\ResourcesModel;
use App\Models\Cruise\CruiseCheckCompanyModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseCheckRectifyModel;
use App\Models\Cruise\CruiseCheckRectifyReplyModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Shop\ShopModel;
use App\Models\System\SystemNotifyCenterModel;
use App\Remote\Rms\RmsShopRemote;
use App\Remote\Rms\RmsUserRemote;
use App\Service\BaseService;
use App\Service\Cruise\Mission\CheckInputService;
use App\Service\OpenShop\Feishu\MainProcessService;
use App\Service\System\SystemNotifyService;
use App\Support\CustomForm\AttributeCruiseSupport;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class CruiseCheckRectifyService extends BaseService
{
    private ?CruiseCheckRectifyModel $cruiseCheckRectifyModel = null;
    private int                      $currentUid;

    public function __construct(int $id, int $currentUid)
    {
        if ($id) {
            $this->cruiseCheckRectifyModel = CruiseCheckRectifyModel::query()->find($id);
        }

        $this->currentUid = $currentUid;
    }

    public static function agg(int $shopId, int $status, int $templateType, array $cruiseCheckCompanyIds = [])
    {
        return CruiseCheckRectifyModel::query()
                                      ->where('templateType', $templateType)
                                      ->where('shopId', $shopId)
                                        ->when($cruiseCheckCompanyIds, function ($query) use ($cruiseCheckCompanyIds) {
                                            $query->whereIn('cruiseCheckCompanyId', $cruiseCheckCompanyIds);
                                        })
                                      ->when($status != CruiseCheckRectifyModel::STATUS_WAIT_TOTAL,
                                          function ($query) use ($status) {
                                              $query->where('status', $status);
                                          })->count();
    }

    public function lists(
        $shopInfo,
        int $status,
        int $pageSize,
        int $pageNum,
        int $startTime,
        int $endTime,
        int $shopId,
        int $templateType,
        array $cruiseCheckCompanyIds = [],
        int $dealUid = 0,
        int $cruiseCheckDetailId = 0,
        array $shopIds = [],
        int $submitStartTime = 0,
        int $submitEndTime = 0
    ): array {
        $paginator = CruiseCheckRectifyModel::query()
                                            ->join('cruise_order', 'cruise_order.id', '=', 'cruise_check_rectify.cruiseOrderId')
                                            ->where('cruise_order.isDeleted', 0)
                                            ->where('cruise_order.status', '!=', CruiseOrderModel::STATUS_CLOSED)
                                            ->with('checkDetailRel')
                                            ->when($dealUid, function ($query) use ($dealUid) {
                                                $query->whereRaw("cruiseCheckDetailId in (select `id` from `cruise_check_details` where `dealUid` = {$dealUid})");
                                            })
                                            ->where('templateType', $templateType)
                                            ->when($shopInfo, function ($query) use ($shopInfo) {
                                                $shopIds   = ShopModel::getShopIdByGeneralSearch($shopInfo);
                                                if ($shopIds) {
                                                    $query->whereIn('cruise_check_rectify.shopId', $shopIds);
                                                } else {
                                                    $query->where('cruise_check_rectify.shopId', 0);
                                                }
                                            })
                                            ->when($shopId, function ($query) use ($shopId) {
                                                $query->where('cruise_check_rectify.shopId', $shopId);
                                            })
                                            ->when($cruiseCheckDetailId, function ($query) use ($cruiseCheckDetailId) {
                                                $query->where('cruise_check_rectify.cruiseCheckDetailId', $cruiseCheckDetailId);
                                            })
                                            ->when($cruiseCheckCompanyIds, function ($query) use ($cruiseCheckCompanyIds) {
                                                $query->whereIn('cruise_check_rectify.cruiseCheckCompanyId', $cruiseCheckCompanyIds);
                                            })
                                            ->when($status != CruiseCheckRectifyModel::STATUS_WAIT_TOTAL,
                                                function ($query) use ($status) {
                                                    $query->where('cruise_check_rectify.status', $status);
                                                })
                                            ->when($startTime, function ($query) use ($startTime) {
                                                $query->where('cruise_check_rectify.createdAt', '>=', $startTime);
                                            })
                                            ->when($endTime, function ($query) use ($endTime) {
                                                $query->where('cruise_check_rectify.createdAt', '<=', $endTime);
                                            })
                                            ->when($shopIds,function ($query)use ($shopIds){
                                                $query->whereIn('cruise_check_rectify.shopId',$shopIds);
                                            })
                                            ->when($submitStartTime,function ($query)use ($submitStartTime){
                                                $query->where('submitEndTime','>=',$submitStartTime);
                                            })
                                            ->when($submitEndTime,function ($query)use ($submitEndTime){
                                                $query->where('submitEndTime','<=',$submitEndTime);
                                            })
                                            ->select('cruise_check_rectify.*')
                                            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $shopIds = array_column($paginator->items(), 'shopId');
        $shops   = collect((new RmsShopApi())->getShopByIds($shopIds)['data']['shopList'] ?? [])->keyBy('id');

        // 商家信息
        $merchants = MainProcessService::getMerchantNameByShopIds($shopIds, $shops);

        return BaseService::pageLists($paginator, function ($item) use ($shops, $merchants) {

            try {
                $project = CheckInputService::getSingleton($item->cruiseOrderId, MerchantAppAuth::$userId)
                                            ->getProject($item->field);
            } catch (\Exception $e) {
                $project = [];
            }

            if (!$project) {
                return null;
            }

            // 机构信息
            if ($item->cruiseCheckCompanyId) {
                $cruiseCheckCompany = CruiseCheckCompanyModel::getDataById($item->cruiseCheckCompanyId);
            } else {
                $cruiseCheckCompany = [];
            }

            return [
                'id'                    => $item->id,
                'text'                  => $project['text'] ?? '',
                'status'                => $item->status,
                'statusText'            => CruiseCheckRectifyModel::STATUS_TEXT[$item->status] ?? '',
                'shopCode'              => $shops[$item->shopId]['kfShopCode'] ?? '',
                'shopName'              => $shops[$item->shopId]['name'] ?? '',
                'createdAt'             => $item->createdAt->toDateString(),
                'endDate'               => $item->submitEndTime > 0 ? date('Y-m-d', $item->submitEndTime) : '-',
                'images'                => collect($project['customAttributes']['auditValue']['files'] ?? [])
                    ->where('type', 'image')
                    ->take(3)
                    ->pluck('url'),
                'merchantName'          => $merchants[$item->shopId]['name'] ?? '',
                'cruiseOrderDetailId'   => $item->checkDetailRel->id ?? 0,
                'cruiseOrderDetailName' => Cache::store('array')
                                                ->remember("cruiseOrderDetailName:{$item->checkDetailRel->taskId}", 30,
                                                    function () use ($item) {
                                                        return (string)optional(optional($item->checkDetailRel)->cruiseTaskRel)->name;
                                                    }),
                'companyName'    => $cruiseCheckCompany['fsCompany']['name'] ?? '',
                'companyContact' => $cruiseCheckCompany['companyManager']['name'] ?? '',
                'dealName'       => object_get($item->checkDetailRel, 'dealName', '-'),   //巡检人
            ];
        });
    }

    public function detail(int $platform = CommonEnum::PLATFORM_FS_MINI): array
    {
        if (!$this->cruiseCheckRectifyModel) {
            BaseService::throwErr("不存在的整改单id");
        }

        $shops = (new RmsShopApi())->getShopByIds([$this->cruiseCheckRectifyModel->shopId])['data']['shopList'][0] ?? [];

        // 商家信息
        $merchants = MainProcessService::getMerchantNameByShopIds([$shops['id'] ?? 0], collect([$shops]));

        // 机构信息
        if ($this->cruiseCheckRectifyModel->cruiseCheckCompanyId) {
            $cruiseCheckCompany = CruiseCheckCompanyModel::getDataById($this->cruiseCheckRectifyModel->cruiseCheckCompanyId);
        } else {
            $cruiseCheckCompany = [];
        }

        $project = (new CheckInputService($this->cruiseCheckRectifyModel->cruiseOrderId, $this->currentUid))
            ->getProject($this->cruiseCheckRectifyModel->field);

        $project['rectifyDetail'] = [
            'status'                => $this->cruiseCheckRectifyModel->status,
            'statusText'            => CruiseCheckRectifyModel::STATUS_TEXT[$this->cruiseCheckRectifyModel->status] ?? '',
            'shopCode'              => $shops['kfShopCode'] ?? '',
            'shopName'              => $shops['name'] ?? '',
            'merchantName'          => $merchants[$this->cruiseCheckRectifyModel->shopId]['name'] ?? '',
            'createdAt'             => $this->cruiseCheckRectifyModel->createdAt->toDateString(),
            'endDate'               => date('Y-m-d H:i:s', $this->cruiseCheckRectifyModel->submitEndTime),
            'auditResult'           => $this->cruiseCheckRectifyModel->lastAuditResult,
            'auditResultText'       => CruiseCheckRectifyModel::AUDIT_TEXT[$this->cruiseCheckRectifyModel->lastAuditResult] ?? '',
            'cruiseOrderDetailId'   => $this->cruiseCheckRectifyModel->checkDetailRel->id ?? 0,
            'cruiseOrderDetailName' => Cache::store('array')
                                            ->remember("cruiseOrderDetailName:{$this->cruiseCheckRectifyModel->checkDetailRel->taskId}",
                                                30,
                                                function () {
                                                    return $this->cruiseCheckRectifyModel->checkDetailRel->cruiseTaskRel->name;
                                                }),
            'isOvertime'            => time() > $this->cruiseCheckRectifyModel->submitEndTime,
            'companyName'    => $cruiseCheckCompany['fsCompany']['name'] ?? '',
            'companyContact' => $cruiseCheckCompany['companyManager']['name'] ?? '',

        ];

        $project['rectifyReply'] = CruiseCheckRectifyReplyModel::getDataByRectifyIds([$this->cruiseCheckRectifyModel->id])[$this->cruiseCheckRectifyModel->id] ?? (object)[];

        $rectifyLog = OperateLogModel::getData(OperateLogModel::BUSINESS_RECTIFY_DETAIL, $this->cruiseCheckRectifyModel->id);
        $userIds = $rectifyLog->pluck('userId')->unique()->filter()->values()->toArray();
        $users = collect(RmsUserRemote::getRmsUserByIds($userIds, ['mobile', 'id']) ?? [])->keyBy('id');

        $project['rectifyLog'] = $rectifyLog
            ->map(function ($log) use ($platform, $users) {

                if ($log->logName == '提交整改内容') {

                    $mobile = $users[$log->userId]['mobile'] ?? '';

                    // 中间四位打*
                    if ($mobile) {
                        $mobile = substr_replace($mobile, '****', 3, 4);
                    }

                    $userName = $log->userName . ' ' . $mobile;
                } elseif ($platform == CommonEnum::PLATFORM_MERCHANT) {
                    $userName = '夸父品控';
                } else {
                    $userName = $log->userName;
                }

                return [
                    'userId'     => $log->userId,
                    'userName'   => $userName,
                    'logId'      => $log->logId,
                    'logName'    => $log->logName,
                    'logContent' => $log->logContent,
                    'createdAt'  => date("m-d H:i", $log->createdAt->timestamp),
                    'status'     => $log->status,
                ];
            });

        return ['project' => $project];
    }

    /**
     * 提交整改内容
     * @param array $files
     * @param string $desc
     * @return void
     * @throws \Exception
     */
    public function submitReply(array $files, string $desc): void
    {
        if (!$this->cruiseCheckRectifyModel) {
            self::throwErr("不存在的整改单");
        }

        if ($this->cruiseCheckRectifyModel->status != CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT) {
            self::throwErr("当前状态不能提交");
        }

        DB::beginTransaction();

        // 整改内容
        $reply = (new CruiseCheckRectifyReplyModel([
            'cruiseCheckRectifyId' => $this->cruiseCheckRectifyModel->id,
            'desc'                 => $desc,
            'rejected'             => CruiseCheckRectifyReplyModel::IS_COMMON
        ]))->addData();

        // resource insert
        foreach ($files as $file) {
            ResourcesModel::moduleBusinessResourcesBuild(
                ResourcesModel::MODULE_TYPE_CHECK,
                ResourcesModel::BUSINESS_CHECK_RECTIFY_FILES,
                'rectifyFiles',
                $reply->id,
                $file['url'],
                ResourcesModel::IS_PUBLIC_YES,
                json_encode(['type' => $file['type']]),
            );
        }
        ResourcesModel::moduleBusinessResourcesSave();

        // 操作日志
        OperateLogModel::add(
            OperateLogModel::BUSINESS_RECTIFY_DETAIL,
            $this->cruiseCheckRectifyModel->id,
            $reply->id,
            '提交整改内容',
            '',
            OperateLogModel::STATUS_OK,
            $this->currentUid,
        );
        OperateLogModel::add(
            OperateLogModel::BUSINESS_RECTIFY_DETAIL,
            $this->cruiseCheckRectifyModel->id,
            0,
            '待审核',
            '',
            OperateLogModel::STATUS_WAIT,
            0,
            '夸父品控'
        );

        // 整改单状态
        $this->cruiseCheckRectifyModel->status = CruiseCheckRectifyModel::STATUS_WAIT_AUDIT;
        $this->cruiseCheckRectifyModel->save();

        DB::commit();
    }

    /**
     * 审核整改提交内容
     * @return void
     */
    public function auditReply(int $auditResult, string $auditText): void
    {
        if (!$this->cruiseCheckRectifyModel) {
            self::throwErr("不存在的整改单");
        }

        if ($this->cruiseCheckRectifyModel->status != CruiseCheckRectifyModel::STATUS_WAIT_AUDIT) {
            self::throwErr("当前状态不能审核");
        }

        DB::beginTransaction();

        if ($auditResult == CruiseCheckRectifyModel::AUDIT_RESULT_OK) {

            // 合格
            $this->cruiseCheckRectifyModel->status          = CruiseCheckRectifyModel::STATUS_FINISH;
            $this->cruiseCheckRectifyModel->lastAuditResult = $auditResult;
            $this->cruiseCheckRectifyModel->lastAuditText   = $auditText;
            $this->cruiseCheckRectifyModel->save();

            OperateLogModel::edit(OperateLogModel::BUSINESS_RECTIFY_DETAIL, $this->cruiseCheckRectifyModel->id,
                "审核结果：合格", "审核意见：{$auditText}");

        } else {

            // 不合格
            $this->cruiseCheckRectifyModel->status          = CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT;
            $this->cruiseCheckRectifyModel->lastAuditResult = $auditResult;
            $this->cruiseCheckRectifyModel->lastAuditText   = $auditText;
            $this->cruiseCheckRectifyModel->save();

            OperateLogModel::edit(OperateLogModel::BUSINESS_RECTIFY_DETAIL, $this->cruiseCheckRectifyModel->id,
                "审核结果：不合格", "审核意见：{$auditText}");

            if ($this->cruiseCheckRectifyModel->templateType != CruiseTemplateModel::TYPE_5) {

                // 驳回商家提醒
                $users = RmsUserRemote::getShopManagerUserByShopId([$this->cruiseCheckRectifyModel->shopId], [], true)['lists'] ?? [];//通过shopId 获得对应店长的 userId
                $userIds = array_column($users, 'userId');

                $notify = SystemNotifyService::save(
                    false,
                    '整改单审核驳回',
                    SystemNotifyCenterModel::NOTIFY_TYPE_3,
                    SystemNotifyCenterModel::NOTIFY_TARGET_1,
                    '',
                    '整改单审核驳回',
                    config('webUrl.notify_web_cdn_url') . '#/pages/audit/rectify/list',
                    SystemNotifyCenterModel::METHOD_TYPE_AUTOMATIC,
                    '您有1项整改项被驳回，请尽快处理！',
                    '',
                    SystemNotifyCenterModel::IS_POPUP_ON,
                    1,
                    $this->cruiseCheckRectifyModel->shopId
                );
                SystemNotifyService::recordLog($notify, '创建消息');
                SystemNotifyService::preSend($notify->id, $userIds);
            }
        }

        DB::commit();
    }

    /**
     * 巡检报告 - 巡检项
     * @param int $cruiseCheckDetailId
     * @return array
     */
    public function reportsLists(
        int $cruiseCheckDetailId,
        int $rectifyStatus = CruiseCheckRectifyModel::STATUS_WAIT_TOTAL,
        bool $emptyRectifyReturn = true
    ): array {
        // 涉及的所有整改单
        $rectifyModels = CruiseCheckRectifyModel::query()
                                                ->where('cruiseCheckDetailId', $cruiseCheckDetailId)
                                                ->when($rectifyStatus != CruiseCheckRectifyModel::STATUS_WAIT_TOTAL,
                                                    function ($query) use ($rectifyStatus) {
                                                        $query->where('status', $rectifyStatus);
                                                    })
                                                ->select('id', 'status', 'lastAuditResult', 'field', 'cruiseOrderId')
                                                ->get()
                                                ->keyBy('field');

        if ($emptyRectifyReturn) {

            if (!$rectifyModels->count()) {
                return [];
            }

            $cruiseOrderId = $rectifyModels->first()['cruiseOrderId'] ?? 0;
            if (!$cruiseOrderId) {
                return [];
            }
        }

        // 所有巡检项
        $cruiseOrderId = CruiseCheckDetailModel::query()->where('id', $cruiseCheckDetailId)->value('orderId') ?? 0;
        $cruiseItems = CheckInputService::getSingleton($cruiseOrderId, 0)->getCruiseItems();

        if ($rectifyModels->count()) {
            $rectifyIds = $rectifyModels->pluck('id')->toArray();

            // 整改内容
            $replyModels = CruiseCheckRectifyReplyModel::getDataByRectifyIds($rectifyIds) ?? [];
        } else {
            $replyModels = collect();
        }

        foreach ($cruiseItems as &$projects) {
            foreach ($projects['projects'] as $k => &$project) {

//                if ($value != 0 && $project['value'] != $value) {
//                    unset($projects['projects'][$k]);
//                }

                $rectifyModel = $rectifyModels[$project['field']] ?? [];
                if (!$rectifyModel) {
                    continue;
                }

                $replyModel = $replyModels[$rectifyModel->id] ?? [];
                if (!$replyModel) {
                    continue;
                }

                $project['rectifyReply']  = $replyModel;
                $project['rectifyDetail'] = [
                    'status'              => $rectifyModel->status,
                    'statusText'          => CruiseCheckRectifyModel::STATUS_TEXT[$rectifyModel->status] ?? '',
                    'lastAuditResult'     => $rectifyModel->lastAuditResult,
                    'lastAuditResultText' => CruiseCheckRectifyModel::AUDIT_TEXT[$rectifyModel->lastAuditResult] ?? '',
                ];
            }

            $projects['projects'] = array_values($projects['projects']);
        }

        return $cruiseItems;
    }

    /**
     * 巡检报告整改项 - 待审核、待整改、已整改（三合一）
     * @param int $cruiseCheckDetailId
     * @return void
     */
    public function reportsListsGroupByRectifyStatus(int $cruiseCheckDetailId): array
    {
        $frame = [
            $value = CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT => [
                'value'    => $value,
                'text'     => CruiseCheckRectifyModel::STATUS_TEXT[$value],
                'projects' => [],
            ],
            $value = CruiseCheckRectifyModel::STATUS_WAIT_AUDIT  => [
                'value'    => $value,
                'text'     => CruiseCheckRectifyModel::STATUS_TEXT[$value],
                'projects' => [],
            ],
            $value = CruiseCheckRectifyModel::STATUS_FINISH      => [
                'value'    => $value,
                'text'     => CruiseCheckRectifyModel::STATUS_TEXT[$value],
                'projects' => [],
            ],
            $value = CruiseCheckRectifyModel::STATUS_CLOSE      => [
                'value'    => $value,
                'text'     => CruiseCheckRectifyModel::STATUS_TEXT[$value],
                'projects' => [],
            ],
        ];

        $lists = $this->reportsLists($cruiseCheckDetailId);

        foreach ($lists as $projects) {
            foreach ($projects['projects'] as $val) {
//                if (!isset($val['rectifyDetail'])) {
//                    continue;
//                }

                if (in_array($val['value'], [AttributeCruiseSupport::CRUISE_CHECK_OK, AttributeCruiseSupport::CRUISE_CHECK_SKIP])) {
                    continue;
                }

                // 不合格 & 现场已整改
                if ($val['value'] == AttributeCruiseSupport::CRUISE_CHECK_FAIL) {
                    $rectifyStatus = $val['customAttributes']['auditValue']['rectifyStatus'] ?? AttributeCruiseSupport::RECTIFY_STATUS_UNDONE;
                    if ($rectifyStatus == AttributeCruiseSupport::RECTIFY_STATUS_DONE) {
                        continue;
                    }
                }

                $rectifyDetailStatus = $val['rectifyDetail']['status'] ?? CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT;

                $frame[$rectifyDetailStatus]['projects'][] = $val;
            }
        }

        foreach ($frame as &$val) {
            $val['text'] = CruiseCheckRectifyModel::STATUS_TEXT[$val['value']] ?? '';
        }

        return collect($frame)->map(function ($item) {
            $item['count'] = count($item['projects']);
            return $item;
        })->values()->toArray();
    }

    /**
     * 待整改批量关闭
     * @param array $ids
     */
    public function batchClose(array $ids)
    {
        $count = CruiseCheckRectifyModel::query()
            ->whereIn('id', $ids)
            ->where('status', CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT)
            ->count();
        if ($count != count($ids)) {
            self::throwErr("整改单状态非待整改");
        }
        CruiseCheckRectifyModel::query()
            ->whereIn('id', $ids)
            ->where('status', CruiseCheckRectifyModel::STATUS_WAIT_SUBMIT)
            ->update(['status' => CruiseCheckRectifyModel::STATUS_CLOSE]);

        Log::info('待整改批量关闭:', [
            'ids'        => $ids,
            'currentUid' => $this->currentUid,
        ]);

        // 操作日志
        OperateLogModel::add(
            OperateLogModel::BUSINESS_RECTIFY_DETAIL,
            0,
            0,
            '待整改批量关闭',
            json_encode(['ids' => $ids]),
            OperateLogModel::STATUS_OK,
            $this->currentUid,
        );
    }
}
